package com.java.st.lib.tools.net;

import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class HttpClientInstance {
	private volatile static CloseableHttpClient httpClient;

	public static CloseableHttpClient getInstance() {
		if (httpClient == null) {
			synchronized (HttpClientInstance.class) {
				if (httpClient == null) {
					Registry<ConnectionSocketFactory> registry = createRegistry();
					PoolingHttpClientConnectionManager poolingConnMgr = new PoolingHttpClientConnectionManager(
							registry);
					poolingConnMgr.setDefaultMaxPerRoute(500);
					poolingConnMgr.setMaxTotal(1000);
					SocketConfig socketConfig = SocketConfig.custom().setSoTimeout(60000).setTcpNoDelay(true).build();
					RequestConfig requestConfig = RequestConfig.custom()
							.setCookieSpec(CookieSpecs.IGNORE_COOKIES)
							.setSocketTimeout(60000)
							.setConnectTimeout(60000)
							.setConnectionRequestTimeout(60000).build();
					poolingConnMgr.setDefaultSocketConfig(socketConfig);
					poolingConnMgr.setValidateAfterInactivity(500);
					HttpClientBuilder httpClientBuilder = HttpClients.custom().setDefaultSocketConfig(socketConfig)
							.setDefaultRequestConfig(requestConfig).setConnectionManager(poolingConnMgr);
					httpClient = httpClientBuilder.build();
				}
			}
		}
		return httpClient;
	}

	private static Registry<ConnectionSocketFactory> createRegistry() {
		SSLContextBuilder builder = new SSLContextBuilder();
		try {
			builder.loadTrustMaterial(null, new TrustStrategy() {
				public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
					return true;
				}
			});
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyStoreException e) {
			e.printStackTrace();
		}
		SSLConnectionSocketFactory sslsf = null;
		try {
			sslsf = new SSLConnectionSocketFactory(builder.build(),
					new String[] { "SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.1","TLSv1.2" }, null, NoopHostnameVerifier.INSTANCE);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyManagementException e) {
			e.printStackTrace();
		}
		Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
				.register("http", new PlainConnectionSocketFactory()).register("https", sslsf).build();
		return registry;
	}

}
